# 作者： 李泉志
# 2025年01月14日12时24分秒
# 2947029073@qq.com
"""
7.re 模块的高级用法
    search(只能搜第一个）
    findall(返回所有匹配项）
    sub 将匹配到的数据进行替换
    split 根据匹配进行切割字符串，并返回一个列表
    finditer 返回一个迭代器，可以遍历所有匹配项

8.python 贪婪和非贪婪
    Python 里数量词默认是贪婪的（在少数语言里也可能是默认非贪婪），总是尝试匹配尽可能多的字符；
    在"*","?","+","{m,n}"后面加上？，使贪婪变成非贪婪。

9.r 的作用
    r 前缀表示原生字符串，即不进行转义，直接匹配字符串中的字符。
    与大多数编程语言相同，正则表达式里使用"\"作为转义字符，这就可能造成反斜杠
    困扰。假如你需要匹配文本中的字符"\"，那么使用编程语言表示的正则表达式里
    将需要2个反斜杠"\\"
    Python里的原生字符串很好地解决了这个问题，有了原生字符串，写出来的表达式更直观。
    r只服务于'\'，不对其他进行转义

10 正则的选项
    re.A 不让\w 匹配汉字
    re.I 是否区分大小写
    re.S 可以让.匹配上\n

练手网站
    https://regexone.com/
    https://regexlearn.com/zh-cn/learn
"""

import re


def add(x):
    ret = x.group()
    return str(int(ret) + 1)


def get_read_times():
    """
    获取文章阅读次数
    """
    ret = re.search(r"\d+", "阅读次数为 9999")
    print(ret.group())

    ret = re.findall(r"\d+", "python = 9999, c = 7890, c++ = 12345")
    print(ret)
    print('-' * 50)

    # 将匹配到的阅读次数加
    # 法1：
    ret = re.sub(r"\d+", '998', "python = 997")
    print(ret)
    # 法2：
    ret = re.sub(r"\d+", lambda x: str(int(x.group()) + 1), "python = 997")
    print(ret)
    ret = re.sub(r"\d+", add, "python = 997")
    print(ret)
    print('-' * 50)

    # sub只替换前两个
    text = "apple apple apple apple"
    pattern = r"apple"
    replacement = "orange"
    new_text = re.sub(pattern, replacement, text, count=2)
    print(new_text)


def find_second_match(pattern, text):
    matches = re.finditer(pattern, text)  # 迭代器
    try:
        next(matches)  # 跳过第一个匹配项
        second_match = next(matches)  # 先赋值，再到下一个：获取第二个匹配项
        return second_match.group()
    except StopIteration:
        return None


def use_findall():
    s = 'hello world, now is 2020/7/20 18:48, 现在是 2020 年 7 月 20 日 18 时 48 分。'
    ret_s = re.sub(r'年|月', r'/', s)
    ret_s = re.sub(r'日', r' ', ret_s)
    ret_s = re.sub(r'时|分', r':', ret_s)
    print(ret_s)

    # findall有问题,search不需要
    # pattern = re.compile(r'\d20{4}/[01]?[0-9]/[1-3]?[0-9]\s(0[0-9]|1[0-9]|2[0-4])\:[0-5][0-9]')
    pattern = re.compile(r'\d{4}/[01]?[0-9]/[1-3]?[0-9]\s(?:0[0-9]|1[0-9]|2[0-4])\:[0-5][0-9]')
    ret = pattern.findall(ret_s)  # 分组前加?:
    print(ret)


def use_sub():
    long_text = """
    <div>
         <p>岗位职责：</p>
<p>完成推荐算法、数据统计、接口、后台等服务器端相关工作</p>
<p><br></p>
<p>必备要求：</p>
<p>良好的自我驱动力和职业素养，工作积极主动、结果导向</p>
<p>&nbsp;<br></p>
<p>技术要求：</p>
<p>1、一年以上 Python 开发经验，掌握面向对象分析和设计，了解设计模式</p>
<p>2、掌握 HTTP 协议，熟悉 MVC、MVVM 等概念以及相关 WEB 开发框架</p>
<p>3、掌握关系数据库开发设计，掌握 SQL，熟练使用 MySQL/PostgreSQL 中的一种<
br></p>
<p>4、掌握 NoSQL、MQ，熟练使用对应技术解决方案</p>
<p>5、熟悉 Javascript/CSS/HTML5，JQuery、React、Vue.js</p>
<p>&nbsp;<br></p>
<p>加分项：</p>
<p>大数据，数理统计，机器学习，sklearn，高性能，大并发。</p>
        </div>
    """
    # print(long_text)
    ret = re.sub(r"<[^>]*>|&nbsp;|\n|\s", "", long_text)
    print(ret)


def use_split():
    ret = re.split(r':| ', 'info:xiaozhang 33 shandong:23')  # 只能有一个空格、:
    print(ret)


def use_greedy():
    s = "This is a number 234-235-22-423"
    ret = re.match(r".+(\d+-\d+-\d+-\d+)", s)
    print(ret.group(1))  # 4-235-22-423,因为.+是贪婪模式，只剩一个4给第一个\d20+匹配，其他全吃了
    ret = re.match(r".+?(\d+-\d+-\d+-\d+)", s)
    print(ret.group(1))

    print(re.match(r"aa(\d+)", "aa2343ddd").group(1))  # 2343
    print(re.match(r"aa(\d+?)", "aa2343ddd").group(1))  # 2
    print(re.match(r"aa(\d+)ddd", "aa2343ddd").group(1))  # 2343
    print(re.match(r"aa(\d+?)ddd", "aa2343ddd").group(1))  # 2343


# 正则选项
def use_options():
    print(re.match(r'\w*', 'abc啊').group())
    print(re.match(r'\w*', 'abc啊', re.A).group())  # 不让\w 匹配汉字

    print(re.match(r'a*', 'aAda').group())  # 区分大小写
    print(re.match(r'a*', 'aAda', re.I).group())  # 不区分大小写

    print('-' * 50)
    print(re.match(r'.*', 'abc\ndef').group())  # 不匹配\n
    print(re.match(r'.*', 'abc\ndef', re.S).group())  # 匹配\n


if __name__ == '__main__':
    # get_read_times()

    # text = "abc123def456ghi789"
    # pattern = r"\d20+"
    # second_match = find_second_match(pattern, text)
    # print(second_match)

    # use_findall()
    # use_sub()
    # use_split()
    # use_greedy()

    use_options()
